namespace SimpleWebServices.Web.UI.Html
{
    using System.Xml.Serialization;
    using SimpleWebServices;
    using SimpleWebServices.Data;
    using SimpleWebServices.Web.UI.Html.Elements;
    using SimpleWebServices.Web.UI.Html.Validation;
    using Xunit;

    public sealed class ControlFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<Control>()
                .DerivesFrom<Element>()
                .IsAbstractBaseClass()
                .Implements<IControl>()
                .Implements<IXmlSerializable>()
                .XmlRoot("control")
                .Result);
        }

        [Fact]
        public void deserialize()
        {
            Control expected = new ControlDerived(new Name("id"))
            {
                Class = "class",
                Disabled = true,
                Language = "fr",
                TabIndex = 1,
                Title = "title"
            };

            string xml = "<control id='id' class='class' lang='fr' title='title' name='id' tabindex='1' disabled='disabled' />";
            Control actual = xml.Deserialize<ControlDerived>();

            Assert.Equal<string>(expected.ToString(), actual.ToString());
        }

        [Fact]
        public void serialize()
        {
            Control obj = new ControlDerived(new Name("id"))
            {
                Class = "class",
                Disabled = true,
                Language = "fr",
                TabIndex = 1,
                Title = "title"
            };

            string xpath = "1=count(/control[@id='id'][@class='class'][@lang='fr'][@title='title'][@name='id'][@tabindex='1'][@disabled='disabled'])";

            Assert.True((bool)obj.Serialize().CreateNavigator().Evaluate(xpath));
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new ControlDerived() as Control);
        }

        [Fact]
        public void ctor_Name()
        {
            Assert.NotNull(new ControlDerived(new Name("id")) as Control);
        }

        [Fact]
        public void ctor_NameNull()
        {
            Assert.NotNull(new ControlDerived(null) as Control);
        }

        [Fact]
        public void prop_Disabled()
        {
            Assert.True(new PropertyExpectations(typeof(ControlDerived).GetProperty("Disabled"))
                .IsAutoProperty<bool>()
                .Result);
        }

        [Fact]
        public void prop_IsValid_whenNullValidator()
        {
            Assert.True(new ControlDerived().IsValid);
        }

        [Fact]
        public void prop_IsValid_getinvalid()
        {
            ControlDerived element = new ControlDerived
            {
                Value = "invalid",
                Validator = new StandardTextValidator(new Label(), 1, 2)
            };

            Assert.False(element.IsValid);
        }

        [Fact]
        public void prop_IsValid_getValid()
        {
            ControlDerived element = new ControlDerived
            {
                Value = "valid",
                Validator = new StandardTextValidator(new Label(), 2, 10)
            };

            Assert.True(element.IsValid);
        }

        [Fact]
        public void prop_Name()
        {
            Assert.True(new PropertyExpectations(typeof(ControlDerived).GetProperty("Name"))
                .IsAutoProperty<Name>()
                .Result);
        }

        [Fact]
        public void prop_Suppress()
        {
            Assert.True(new PropertyExpectations(typeof(ControlDerived).GetProperty("Suppress"))
                .IsAutoProperty<bool>()
                .Result);
        }

        [Fact]
        public void prop_TabIndex()
        {
            Assert.True(new PropertyExpectations(typeof(ControlDerived).GetProperty("TabIndex"))
                .IsAutoProperty<int?>()
                .Result);
        }

        [Fact]
        public void prop_Title()
        {
            Assert.True(new PropertyExpectations(typeof(ControlDerived).GetProperty("Title"))
                .IsAutoProperty<char?>()
                .Result);
        }

        [Fact]
        public void prop_Validator()
        {
            Assert.True(new PropertyExpectations(typeof(ControlDerived).GetProperty("Validator"))
                .IsAutoProperty<IValidate>()
                .Result);
        }

        [Fact]
        public void prop_Value()
        {
            Assert.True(new PropertyExpectations(typeof(ControlDerived).GetProperty("Value"))
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void op_ToHiddenInput()
        {
            Control obj = new ControlDerived
            {
                Id = "id",
                Name = "name",
                Value = "value"
            };

            HiddenInput actual = obj.ToHiddenInput();

            Assert.Equal<string>("id", actual.Id);
            Assert.Equal<string>("name", actual.Name);
            Assert.Equal<string>("value", actual.Value);
        }

        [Fact]
        public void op_ToDataCollection()
        {
            Control obj = new ControlDerived("name");
            obj.Value = "value";

            DataCollection expected = new DataCollection();
            expected.Add("name", "value");

            DataCollection actual = obj.ToDataCollection();

            Assert.Equal<DataCollection>(expected, actual);
        }

        [Fact]
        public void op_Update_Name_string()
        {
            Name name = new Name("name");

            Control obj = new ControlDerived(name);

            Assert.Null(obj.Value);

            string expected = "value";
            obj.Update(name, expected);
            string actual = obj.Value;

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_Update_NameNull_string()
        {
            Control obj = new ControlDerived(new Name("name"));

            obj.Update(null, "value");
            Assert.Null(obj.Value);
        }

        [Fact]
        public void op_Update_Name_stringNull()
        {
            Name name = new Name("name");

            Control obj = new ControlDerived(name)
            {
                Value = "value"
            };

            obj.Update(name, null);

            Assert.Null(obj.Value);
        }

        [Fact]
        public void op_Update_Name_stringEmpty()
        {
            Name name = new Name("name");

            Control obj = new ControlDerived(name);

            Assert.Null(obj.Value);

            string expected = string.Empty;
            obj.Update(name, expected);
            string actual = obj.Value;

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_Update_NameDiffers_string()
        {
            Control obj = new ControlDerived(new Name("foo"));

            obj.Update(new Name("bar"), "value");
            Assert.Null(obj.Value);
        }
    }
}